package com.socket;

import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fazecast.jSerialComm.*;
import com.mybatisdemo.entity.IotMessage;
import com.mybatisdemo.service.IotMessageService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 命令行版本的串口温湿度监控程序
 */
@Component
public class SerialConsoleMonitor {

    private static IotMessageService iotMessageService;

    @Autowired
    public void setIotMessageService(IotMessageService iotMessageService) {
        SerialConsoleMonitor.iotMessageService = iotMessageService;
    }

    @Value("${iot-param.com-port}")
    private String comPort;

    @Value("${iot-param.baud-rate}")
    private String baudRate;

    public static JSONObject jsonObject = new JSONObject();
    public  JSONObject tempObject = new JSONObject();

    @Autowired
    private WebSocketServer webSocketServer;
    private final ScheduledExecutorService service= Executors.newSingleThreadScheduledExecutor();

    private static SerialPort serialPort;
    private static boolean running = true;
    private static FileWriter dataLogger;
    private static boolean debugMode = true; // 默认开启调试模式
    private static boolean hexMode = false;  // 十六进制显示模式

    @PostConstruct
    public void init() throws IOException {
        service.schedule(() -> {
            try {
                webSocketServer.sendMessageToAll("===项目启动10秒后只执行一次====");
                startIot();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        },10, TimeUnit.SECONDS);

    }

    public static void main(String[] args) {
        String line = "b:0";
        String str[] = line.split(":");
        if(str[0].trim().matches("[a-zA-Z]")){
            System.out.println(111);
        }else{
            System.out.println(22);
        }
//        new SerialConsoleMonitor().startIot();
    }

    public  void startIot(){

        System.out.println("串口温湿度监控程序 (命令行版)");
        System.out.println("---------------------------");

        // 初始化数据记录器
        try {
            SimpleDateFormat fileFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
            dataLogger = new FileWriter("temp_humidity_" + fileFormat.format(new Date()) + ".csv");
            dataLogger.write("时间戳,温度(°C),湿度(%)\n");
            dataLogger.flush();
            System.out.println("数据将保存到: temp_humidity_" + fileFormat.format(new Date()) + ".csv");
        } catch (IOException e) {
            System.err.println("无法创建数据日志文件: " + e.getMessage());
            return;
        }

        // 列出可用串口
        SerialPort[] ports = SerialPort.getCommPorts();
        if (ports.length == 0) {
            System.out.println("没有找到可用的串口");
            closeDataLogger();
            return;
        }

        System.out.println("\n可用串口列表:");
        for (int i = 0; i < ports.length; i++) {
            System.out.println((i + 1) + ". " + ports[i].getSystemPortName() +
                    " - " + ports[i].getDescriptivePortName());
        }

        // 选择串口
        Scanner scanner = new Scanner(System.in);
        int portChoice = -1;

        while (portChoice < 1 || portChoice > ports.length) {
            System.out.print("\n请选择串口 (1-" + ports.length + "): ");
            try {
                portChoice = Integer.parseInt(comPort);    //========com口===========================================
            } catch (NumberFormatException e) {
                System.out.println("无效的输入，请输入数字");
            }
        }

        // 选择波特率
        int[] baudRates = {1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600};
        System.out.println("\n可用波特率:");
        for (int i = 0; i < baudRates.length; i++) {
            System.out.println((i + 1) + ". " + baudRates[i]);
        }

        int baudChoice = -1;
        while (baudChoice < 1 || baudChoice > baudRates.length) {
            System.out.print("\n请选择波特率 (1-" + baudRates.length + "): ");
            try {
                baudChoice = Integer.parseInt(baudRate);  //=================================
            } catch (NumberFormatException e) {
                System.out.println("无效的输入，请输入数字");
            }
        }

        // 选择数据位
        int[] dataBits = {7, 8};
        System.out.println("\n数据位:");
        for (int i = 0; i < dataBits.length; i++) {
            System.out.println((i + 1) + ". " + dataBits[i] + " 位");
        }

        int dataBitsChoice = -1;
        while (dataBitsChoice < 1 || dataBitsChoice > dataBits.length) {
            System.out.print("\n请选择数据位 (1-" + dataBits.length + "): ");
            try {
                dataBitsChoice = Integer.parseInt("2"); //============================
            } catch (NumberFormatException e) {
                System.out.println("无效的输入，请输入数字");
            }
        }

        // 选择停止位
        int[] stopBits = {1, 2};
        System.out.println("\n停止位:");
        for (int i = 0; i < stopBits.length; i++) {
            System.out.println((i + 1) + ". " + stopBits[i] + " 位");
        }

        int stopBitsChoice = -1;
        while (stopBitsChoice < 1 || stopBitsChoice > stopBits.length) {
            System.out.print("\n请选择停止位 (1-" + stopBits.length + "): ");
            try {
                stopBitsChoice = Integer.parseInt("1"); //=====停止位==========================
            } catch (NumberFormatException e) {
                System.out.println("无效的输入，请输入数字");
            }
        }

        // 选择奇偶校验
        String[] parityOptions = {"无", "奇校验", "偶校验"};
        int[] parityValues = {SerialPort.NO_PARITY, SerialPort.ODD_PARITY, SerialPort.EVEN_PARITY};
        System.out.println("\n奇偶校验:");
        for (int i = 0; i < parityOptions.length; i++) {
            System.out.println((i + 1) + ". " + parityOptions[i]);
        }

        int parityChoice = -1;
        while (parityChoice < 1 || parityChoice > parityOptions.length) {
            System.out.print("\n请选择奇偶校验 (1-" + parityOptions.length + "): ");
            try {
                parityChoice = Integer.parseInt("1"); //===========奇偶校验==============
            } catch (NumberFormatException e) {
                System.out.println("无效的输入，请输入数字");
            }
        }

        // 配置并打开串口
        serialPort = ports[portChoice - 1];
        int baudRate = baudRates[baudChoice - 1];
        int dataBit = dataBits[dataBitsChoice - 1];
        int stopBit = stopBits[stopBitsChoice - 1];
        int parity = parityValues[parityChoice - 1];

        serialPort.setBaudRate(baudRate);
        serialPort.setNumDataBits(dataBit);
        serialPort.setNumStopBits(stopBit);
        serialPort.setParity(parity);
        serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);

        System.out.println("\n串口配置:");
        System.out.println("  端口: " + serialPort.getSystemPortName());
        System.out.println("  波特率: " + baudRate);
        System.out.println("  数据位: " + dataBit);
        System.out.println("  停止位: " + stopBit);
        System.out.println("  奇偶校验: " + parityOptions[parityChoice - 1]);

        System.out.println("\n尝试连接到 " + serialPort.getSystemPortName() + "...");

        // 尝试多种模式打开串口
        boolean portOpened = false;

        // 尝试使用独占模式打开
        serialPort.closePort(); // 确保先关闭
        serialPort.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 0, 0);
        portOpened = serialPort.openPort(2000);

        if (!portOpened) {
            System.out.println("独占模式打开失败，尝试非独占模式...");
            serialPort.closePort();
            serialPort.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 0, 0);
            portOpened = serialPort.openPort(0, SerialPort.TIMEOUT_NONBLOCKING, SerialPort.TIMEOUT_NONBLOCKING);
        }

        if (portOpened) {
            System.out.println("连接成功！开始接收数据...");
            System.out.println("命令帮助:");
            System.out.println("  q - 退出程序");
            System.out.println("  d - 切换调试模式 (当前: " + (debugMode ? "开启" : "关闭") + ")");
            System.out.println("  h - 切换十六进制显示模式 (当前: " + (hexMode ? "开启" : "关闭") + ")");
            System.out.println("  t - 发送测试数据");
            System.out.println("  c - 清空缓冲区");

            // 启动数据读取线程
            Thread readThread = new Thread(() -> readSerialData());
            readThread.setDaemon(true);
            readThread.start();

            // 监听用户命令
            while (running) {
                String input = scanner.nextLine().trim().toLowerCase();
                if (input.equals("q")) {
                    running = false;
                    break;
                } else if (input.equals("d")) {
                    debugMode = !debugMode;
                    System.out.println("调试模式: " + (debugMode ? "开启" : "关闭"));
                } else if (input.equals("h")) {
                    hexMode = !hexMode;
                    System.out.println("十六进制显示模式: " + (hexMode ? "开启" : "关闭"));
                } else if (input.equals("t")) {
                    sendTestData();
                } else if (input.equals("c")) {
                    clearBuffer();
                }
            }

            // 关闭资源
            System.out.println("正在关闭...");
            if (serialPort.isOpen()) {
                serialPort.closePort();
            }
            closeDataLogger();

        } else {
            System.err.println("无法打开串口，请检查是否被其他程序占用");
            System.err.println("尝试关闭所有可能占用串口的程序，如串口助手等");
            closeDataLogger();
        }

        scanner.close();
    }
    
    // 清空缓冲区
    private  void clearBuffer() {
        try {
            if (serialPort.isOpen()) {
                int available = serialPort.bytesAvailable();
                if (available > 0) {
                    byte[] buffer = new byte[available];
                    serialPort.readBytes(buffer, available);
                    System.out.println("已清空 " + available + " 字节的缓冲区数据");
                } else {
                    System.out.println("缓冲区为空，无需清理");
                }
            }
        } catch (Exception e) {
            System.err.println("清空缓冲区时出错: " + e.getMessage());
        }
    }
    
    // 发送测试数据到串口
    private  void sendTestData() {
        try {
            String testData = "25,60\n";
            byte[] bytes = testData.getBytes();
            int result = serialPort.writeBytes(bytes, bytes.length);
            if (result == bytes.length) {
                System.out.println("测试数据发送成功: " + testData.trim());
            } else {
                System.err.println("测试数据发送失败");
            }
        } catch (Exception e) {
            System.err.println("发送测试数据时出错: " + e.getMessage());
        }
    }
    
    private  void readSerialData() {
        // 使用无阻塞模式，避免超时错误
        serialPort.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 0, 0);
        
        byte[] buffer = new byte[1024];
        StringBuilder lineBuffer = new StringBuilder();
        long lastDataTime = 0;
        
        System.out.println("开始监听串口数据...");
        
        try {
            while (running && serialPort.isOpen()) {
                try {
                    // 读取可用数据
                    int bytesAvailable = serialPort.bytesAvailable();
                    
                    if (bytesAvailable > 0) {
                        lastDataTime = System.currentTimeMillis();
                        int bytesRead = serialPort.readBytes(buffer, Math.min(bytesAvailable, buffer.length));
                        
                        if (bytesRead > 0) {
                            // 将读取的字节转换为字符串并添加到缓冲区
                            String data = new String(buffer, 0, bytesRead);
                            
                            // 调试模式下显示原始字节
                            if (debugMode) {
                                System.out.println("接收到 " + bytesRead + " 字节数据");
                                if (hexMode) {
                                    System.out.print("十六进制: ");
                                    for (int i = 0; i < bytesRead; i++) {
                                        System.out.printf("%02X ", buffer[i] & 0xFF);
                                    }
                                    System.out.println();
                                }
                                
                                System.out.println("ASCII: " + data.replace("\n", "\\n").replace("\r", "\\r"));
                            }
                            
                            lineBuffer.append(data);
                            
                            // 处理完整行 - 支持多种行结束符
                            processLines(lineBuffer);

                        }
                    } else {
                        // 如果超过10秒没有数据，显示提示
                        long now = System.currentTimeMillis();
                        if (lastDataTime > 0 && now - lastDataTime > 10000) {
                            System.out.println("已经 " + ((now - lastDataTime) / 1000) + " 秒没有接收到数据...");
                            lastDataTime = now; // 重置，避免持续打印
                        }
                    }
                    
                    // 短暂休眠，避免CPU占用过高
                    Thread.sleep(50);
                    
                } catch (Exception e) {
                    if (running) {
                        System.err.println("读取串口数据时发生错误: " + e.getMessage());
                        e.printStackTrace();
                        // 出错后短暂休眠，避免错误消息刷屏
                        Thread.sleep(1000);
                    }
                }
            }
        } catch (Exception e) {
            if (running) {
                System.err.println("串口读取线程异常: " + e.getMessage());
                e.printStackTrace();
            }
        }
    }
    
    // 处理可能包含多种行结束符的数据
    private  void processLines(StringBuilder buffer) {
        int pos;
        // 检查CR+LF
        while ((pos = buffer.indexOf("\r\n")) != -1) {
            processLine(buffer.substring(0, pos));
            buffer.delete(0, pos + 2);
        }
        
        // 检查单独的LF
        while ((pos = buffer.indexOf("\n")) != -1) {
            processLine(buffer.substring(0, pos));
            buffer.delete(0, pos + 1);
        }
        
        // 检查单独的CR
        while ((pos = buffer.indexOf("\r")) != -1) {
            processLine(buffer.substring(0, pos));
            buffer.delete(0, pos + 1);
        }
    }
    
    // 处理单行数据
    private  String processLine(String line) {
        if (line == null || line.trim().isEmpty()) {
            return null;
        }
        
        // 打印原始数据
        System.out.println("收到数据: " + line);

        /**
         *   温湿度： c:温度,湿度
         * 人体感知： p:0(无人),p:1(有人)
         *   蜂鸣器： b:0(低电频),b:1(高电频)  默认：高电频
         */
        try {
            String str[] = line.split(":");
            String isLetter = str[0].trim();
            if(isLetter.matches("[a-zA-Z]")){
                //判断是温湿度
                if(isLetter.equals("c")){
                    String strTem[] = str[1].trim().split(",");
                    jsonObject.put("wendu",strTem[0].trim());
                    jsonObject.put("jiawan",strTem[1].trim());
                }
                //判断是人体感知
                if(isLetter.equals("p")){
                    jsonObject.put("rentiganzhi",str[1].trim());
                }
                //判断是蜂鸣器
                if(isLetter.equals("b")){
                    jsonObject.put("fengmingqi",str[1].trim());
                }
                webSocketServer.sendMessageToAll(jsonObject+"");
                queryJsonObject();
            }else{
                System.out.println("无效数据");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 解析数据（格式：温度,湿度）
        String[] data = line.split(",");
        if (data.length == 2) {
            try {
                // 获取当前时间戳
                String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                
                // 尝试解析数字，去除可能的非数字字符
                String tempStr = data[0].trim().replaceAll("[^0-9\\-\\.]", "");
                String humStr = data[1].trim().replaceAll("[^0-9\\-\\.]", "");
                
                if (tempStr.isEmpty() || humStr.isEmpty()) {
                    System.out.println("数据格式错误: 无法提取数字");
                    return null;
                }
                
                // 支持浮点数
                float temperature = Float.parseFloat(tempStr);
                float humidity = Float.parseFloat(humStr);
                
                // 检查数据是否在合理范围内
                if (temperature < -40 || temperature > 80) {
                    System.out.println("温度数据超出合理范围: " + temperature);
                    return null;
                }
                
                if (humidity < 0 || humidity > 100) {
                    System.out.println("湿度数据超出合理范围: " + humidity);
                    return null;
                }
                
                // 记录并显示数据
                System.out.println(String.format("[%s] 温度: %.1f°C, 湿度: %.1f%%", 
                                               timestamp, temperature, humidity));
                
                // 写入CSV文件
                try {
                    dataLogger.write(timestamp + "," + temperature + "," + humidity + "\n");
                    dataLogger.flush();
                } catch (IOException e) {
                    System.err.println("写入数据日志时发生错误: " + e.getMessage());
                }
                
            } catch (NumberFormatException e) {
                System.out.println("数据格式错误: " + line + " (" + e.getMessage() + ")");
            }
        } else {
            System.out.println("数据格式错误: 需要两个值(温度,湿度)，但收到 " + data.length + " 个值");
        }
        return line;
    }

    /**
     * 在添加数据之前，判断该数据和上一次数据是否相同，相同放弃添加，否则保持到数据库
     *
     */
    public void queryJsonObject(){
        System.out.println("tempObject"+tempObject);
        System.out.println("jsonObject:"+jsonObject);
        if (jsonObject.equals(tempObject)){
            return;
        }
        tempObject = JSON.parseObject(jsonObject.toJSONString());

        IotMessage iotMessage = new IotMessage();
        iotMessage.setRenti(jsonObject.getIntValue("rentiganzhi"));
        iotMessage.setWendu(jsonObject.getIntValue("wendu"));
        iotMessage.setJiawan(jsonObject.getIntValue("jiawan"));
        iotMessage.setFengmingqi(jsonObject.getIntValue("fengmingqi"));

        // 格式化日期时间
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = sdf.format(date);
        iotMessage.setCreatetime(formattedDateTime);
        iotMessageService.save(iotMessage);
    }

    /**
     * 打开蜂鸣器
     * @throws InterruptedException
     */
    public  void openBuzzer() throws InterruptedException {
        Thread.sleep(1000);
        String atCommand3 = "AT+WTGPIO=9,0\r\n"; // 示例指令
        byte[] data3 = atCommand3.getBytes();
        serialPort.writeBytes(data3, data3.length);
        System.out.print("Sent: " + atCommand3);
    }

    /**
     * 关闭蜂鸣器
     * @throws InterruptedException
     */
    public  void closeBuzzer() throws InterruptedException {
        Thread.sleep(1000);
        String atCommand3 = "AT+WTGPIO=9,1\r\n"; // 示例指令
        byte[] data3 = atCommand3.getBytes();
        serialPort.writeBytes(data3, data3.length);
        System.out.print("Sent: " + atCommand3);
    }
    
    private  void closeDataLogger() {
        if (dataLogger != null) {
            try {
                dataLogger.close();
                System.out.println("数据日志文件已关闭");
            } catch (IOException e) {
                System.err.println("关闭数据日志文件时发生错误: " + e.getMessage());
            }
        }
    }
} 